﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace S
{

    //     一、什么是策略模式？
    //策略模式（Strategy Pattern） 是一种 行为型设计模式，其核心思想是：
    //定义一系列算法，将每个算法封装起来，使它们可以互相替换，并使算法的变化独立于使用算法的客户端。

    //换句话说：
    //把一组可变的业务逻辑或算法抽象出来。
    //把它们封装成一个个独立的“策略类”。
    //客户端通过组合而非条件语句（如 if-else）来决定使用哪个策略。

    //    二、适用场景
    //策略模式适用于以下场景：
    //1.程序中有多个类似的算法，且你希望可以在运行时灵活切换。
    //2.使用大量 if-else 或 switch 来处理不同的行为逻辑。
    //3.希望解耦算法的实现和其使用者。
    //4.多种行为仅在部分逻辑上有所不同时，可以将不同逻辑提取成策略。


    //    三、结构组成（UML）
    //角色                                说明
    //Strategy（抽象策略）	            定义算法或行为的接口
    //ConcreteStrategy（具体策略）	    实现不同的算法或行为
    //Context（上下文环境类）	            持有策略引用，面向接口调用


    //    四、示例：商场满减策略
    //一个购物系统中，不同节日或不同客户等级使用不同的价格计算策略



    //    五、优缺点分析
    //✅ 优点
    //遵循开闭原则：如果要新增策略的时候, 不需要修改原有逻辑。
    //消除if-else：将条件判断转化为多态调用。
    //灵活切换行为：运行时可自由选择策略。

    //    六、策略模式 vs 状态模式 对比
    //                     策略模式                    状态模式
    //意图                抽象可变算法              抽象对象状态行为
    //是否切换策略        客户端主动切换             状态对象内部切换
    //是否感知上下文       ❌ 无	                        ✅ 有
    //应用重点            同一行为不同算法           同一对象的行为随状态变化



    //    七、实际开发中的应用场景
    //  场景                   示例
    //商城促销          满减、打折、折上折
    //支付系统          支付宝、微信、信用卡 支付策略
    //日志策略          输出到控制台、文件、数据库
    //游戏开发          角色行为：攻击、移动、技能释放策略
    //排序算法          快排、归并、冒泡算法可切换
    //AI/自动控制       机器人不同决策算法


    //    八、总结一句话
    //当你的代码中有“多种可互换的行为或算法”，并且希望能灵活地替换或添加新的算法而不修改原有逻辑，就使用策略模式。
    //套用策略模式可以优化行为切换逻辑



    #region 抽象策略接口

    /// <summary>
    /// 定价策略接口
    /// </summary>
    public interface IPricingStrategy
    {
        /// <summary>
        /// 虚实现,计算价格,在派生类中再实现具体的价格计算
        /// </summary>
        /// <param name="originalPrice"></param>
        /// <returns></returns>
        double CalculatePrice(double originalPrice);
    }
    #endregion



    #region 具体策略实现

    /// <summary>
    /// 正常价格
    /// </summary>
    public class NormalPricing : IPricingStrategy
    {
        public double CalculatePrice(double originalPrice) => originalPrice;
    }

    /// <summary>
    /// 打折价格
    /// </summary>
    public class DiscountPricing : IPricingStrategy
    {
        public double CalculatePrice(double originalPrice) => originalPrice * 0.8;
    }

    /// <summary>
    /// Vip用户价格
    /// </summary>
    public class VipPricing : IPricingStrategy
    {
        public double CalculatePrice(double originalPrice) => originalPrice * 0.7;
    }



    #endregion


    #region 上下文环境类
    public class PriceContext
    {
        private IPricingStrategy strategy;   //定价策略接口

        public PriceContext(IPricingStrategy strategy)
        {
            this.strategy = strategy;
        }

        /// <summary>
        /// 设置定价策略
        /// </summary>
        /// <param name="strategy"></param>
        public void SetStrategy(IPricingStrategy strategy)
        {
            this.strategy = strategy;
        }

        /// <summary>
        /// 计算最终价格
        /// </summary>
        /// <param name="originalPrice"></param>
        /// <returns></returns>
        public double GetFinalPrice(double originalPrice)
        {
            return strategy.CalculatePrice(originalPrice);
        }
    }
    #endregion





    class Program
    {
        static void Main(string[] args)
        {
            //func1();

            func2();

            Console.ReadKey();

        }

        static void func1()
        {
            Context context = new Context();
            context.Algorithm();
        }

        static void func2()
        {
            double price = 100;

            var context = new PriceContext(new NormalPricing());
            Console.WriteLine("普通用户价格: " + context.GetFinalPrice(price));

            context = new PriceContext(new DiscountPricing());
            Console.WriteLine("打折活动之后的价格: " + context.GetFinalPrice(price));

            context.SetStrategy(new VipPricing());
            Console.WriteLine("VIP用户价格: " + context.GetFinalPrice(price));

        }

    }
}
